1. Field of the Invention
The present invention relates to systems and methods for protecting software from unauthorized copying and/or execution, and in particular to a system and method that protects software via shell code that contains embedded license information and/or that communicates with a protected application via a secure tunnel.
2. Description of the Related Art
Software piracy is an ongoing problem for software vendors. Many techniques for discouraging software piracy have been developed, and products incorporating those techniques are available for use by software vendors to secure their software applications from unauthorized copying and/or use.
One software application protection technique uses link-in modules that require the developer to modify the original application code to call specific functions, for example, functions that check for license conditions. Another protection technique is called shelling. Shelling ordinarily does not require changes to the application code. With the shelling technique, a shell generating process reads the original application executable and produces a modified, new executable as a so-called shelled application which contains an “outer layer” of protection code that encapsulates the original application. Further, when shelling is used, one or more application sections, such as executable code, data, import tables, resources, and the like, can be protected via encryption and/or compression when the shell code is generated, and the shell makes the protected code sections available as needed when the protected application runs.
One function typically performed by the shell is to confirm that a valid license for the application exists. For example, a traditional shell-based application protection solution will typically pack the protected application with shell code that stores license or key information in a storage location separate from the protected application. The licensing information can be stored in a registry, database, file, hidden disk sector, or the like. One or more application programming interfaces (APIs) are provided to access the license information, and the shell code can call the APIs to verify that the protected application is properly licensed.
One vulnerability inherent in shelling is that the software application program protection is provided only by the outer layer of protection. Consequently, a cracker may be able to gain access to the protected application by cracking only the outer layer of protection. When the shelled application launches, the shell code executes before the original application code, and code execution usually proceeds in a fixed, identifiable pattern. A cracker can follow the code execution (for example, by running the shelled program under a debugger), and once the code execution sequence is understood, the cracker can modify the code (for example, by patching the shelled application executable) to bypass and/or disable license checking.
Link-in modules and shelling can also be used together. For example, in one scenario the shell code can be appended to the encrypted and/or compressed application sections. When the shelled application first executes, the shell initially gains control and can perform security-related functions such as checking application integrity, checking for the presence of a debugger, decrypting and/or decompressing application sections, and initializing application processes such as import functions and relocation tables, before passing control to the application. The original application code can also be modified to redirect some system APIs to the shell code. The application can then continue to interact with the shell code after control is transferred to the application. Furthermore, self-modifying code functions can be provided by the shell whereby, for example, certain application code snippets are encrypted at runtime, and the shell code can decrypt those code snippets before they are executed, and encrypt them again after executing.
However, in solutions that utilize shelling, the application code and the shell code of the shelled application reside in different sections of memory having identifiably different addresses. Prior art shelling solutions do not mask the difference between application code addresses and shell code addresses. A cracker may therefore be able to unpack the protected application code and determine which code is part of the shell, and which is part of the application the shell protects. If so, the cracker may then be able to remove or modify the link between shell code and application code. For example, encryption and decryption of code during program execution can be disabled by using no-operation (NOP) instructions to replace decrypt and encrypt instructions.
FIG. 1 shows an example of a traditional self-modifying code feature being implemented. As shown, two macros are used by the packing tool to locate the code to be protected, SHELL_CRYPT_BEGIN, and SHELL_CRYPT_END. After compiling and packing, the disassembled code will be shown in FIGS. 2A and 2B.
After the application is compiled, the protective shell code is generated and a shelled application executable is generated. The shelled application executable can then be examined by a cracker using a debug tool, such as OllyDbg, for example, to disassemble the shelled application executable, or binary code. OllyDbg is a debugger that emphasizes binary code analysis. It traces registers, recognizes procedures, API calls, switches, tables, constants, and strings, and locates routines from object files and libraries. Such tools can be used to reverse engineer and crack programs.
FIG. 2A shows an illustrative snippet of such disassembled code. Program addresses are shown at the beginning of each line, and all have the format 0040XXXX. The code at address 004013A2 calls the code at address 004A6B81 (top line of code) to decrypt the subsequent lines of code. After executing the code at address 004013A2, the code is changed as shown in FIG. 2B. It is apparent that the called addresses 004A6B81 and 004AADBB (underlined in the call statements at lines 004013A2 and 004013BD in FIGS. 2A and 2B) are located in different address sections than the program code addresses that are indicated at the beginning of each line of code, i.e., at addresses 0040XXXX. A cracker could surmise that address locations of the form 0040XXXX belong to the application code address space, while address locations of the form 004AXXXX belong to the shell code address space.
Different code sections are illustrated in FIG. 3, wherein different blocks indicate code sections located in different address spaces. As shown, the address spaces of the different code sections have identifiable boundaries. Illustratively, during program execution the shell code can decrypt and encrypt sections of application code as needed, thereby enhancing the security of the application code. Even so, a cracker might be able to analyze the program, recognize the existence of the decryption and encryption shell processes, and remove the link between the shell code and the application code, for example, by using no-operation (NOP) instructions to replace the encryption instructions. Similarly, a cracker might be able to recognize the existence of license checking processes, and remove the link between the shelled application code and the license information stored outside of the shelled application.
Accordingly, there is a need for an application protection technique that resists cracking by making it more difficult for a cracker to disable license checking and/or modify communications between application code and shell code.